package com.qlylkj.lbk.model.api

import com.google.gson.Gson
import com.qlylkj.lbk.app.Constant
import com.qlylkj.lbk.app.PreferenceHelper
import com.qlylkj.lbk.model.bean.base.ResponseEntity
import com.qlylkj.lbk.model.bean.base.ResponseList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import java.io.IOException

/**
 *    author : duanguosen
 *    date   : 2019/11/25
 *    desc   :
 */
open class BaseRepository {

    companion object {

        /**
         * 请求成功
         */
        const val HTTP_SUCCESS_0 = 0
        /**
         * 请求成功
         */
        const val HTTP_SUCCESS_200 = 200
        /**
         * 登录失效
         */
        const val LOGON_FAILURE = 20

        private val jsonContentType = "application/json; charset=utf-8".toMediaTypeOrNull()

        private val multipartContentType = "image/jpg".toMediaTypeOrNull()
    }

    fun requestJsonBody(map: MutableMap<String, Any>): RequestBody {
        return Gson().toJson(map).toRequestBody(jsonContentType)
    }

    fun requestMultipartBody(file: File): MultipartBody.Part{
        return MultipartBody.Part.createFormData("file",file.name,file.asRequestBody(multipartContentType))
    }

    private fun resultErrorMessage(errorMessage: String): String {
        return if (PreferenceHelper.hasNetwork) errorMessage else Constant.RESULT_NETWORK_ERROR
    }

    suspend fun <T : Any> apiCallEntity(call: suspend () -> ResponseEntity<T>): ResponseEntity<T> {
        return call.invoke()
    }

    suspend fun <T : Any> apiCallList(call: suspend () -> ResponseList<T>): ResponseList<T> {
        return call.invoke()
    }

    suspend fun <T : Any> safeApiCallEntity(
        call: suspend () -> ResultResponse<T>,
        errorMessage: String
    ): ResultResponse<T> {
        return try {
            call()
        } catch (e: Exception) {
            ResultResponse.Error(
                IOException(
                    resultErrorMessage(
                        errorMessage
                    ), e
                )
            )
        }
    }

    suspend fun <T : Any> safeApiCallList(
        call: suspend () -> ResultResponse<MutableList<T>>,
        errorMessage: String
    ): ResultResponse<MutableList<T>> {
             return try {
                call()
            } catch (e: Exception) {
                 ResultResponse.Error(
                     IOException(
                         resultErrorMessage(
                             errorMessage
                         ), e
                     )
                 )
            }
    }

    suspend fun <T : Any> executeEntityResponse(
        response: ResponseEntity<T>, successBlock: (suspend CoroutineScope.() -> Unit)? = null,
        errorBlock: (suspend CoroutineScope.() -> Unit)? = null
    ): ResultResponse<T> {
        return withContext(Dispatchers.IO) {
            when (response.code) {
                HTTP_SUCCESS_0,HTTP_SUCCESS_200 -> {
                    successBlock?.let { it() }
                    response.data?.let {
                        ResultResponse.SuccessEntity(it)
                    } ?: ResultResponse.Success(response.message)
                }
                LOGON_FAILURE -> {
                    errorBlock?.let { it() }
                    ResultResponse.LoginFailure("登录过期,请重新登录")
                }
                else -> {
                    errorBlock?.let { it() }
                    ResultResponse.Error(IOException(response.message))
                }
            }
        }
    }

    suspend fun <T : Any> executeListResponse(
        response: ResponseList<T>, successBlock: (suspend CoroutineScope.() -> Unit)? = null,
        errorBlock: (suspend CoroutineScope.() -> Unit)? = null
    ): ResultResponse<MutableList<T>> {
        return withContext(Dispatchers.IO) {
            when (response.code) {
                HTTP_SUCCESS_0,HTTP_SUCCESS_200 -> {
                    successBlock?.let { it() }
                    ResultResponse.SuccessList(response.data ?: mutableListOf())
                }
                LOGON_FAILURE -> {
                    errorBlock?.let { it() }
                    ResultResponse.LoginFailure("登录过期,请重新登录")
                }
                else -> {
                    errorBlock?.let { it() }
                    ResultResponse.Error(IOException(response.message))
                }
            }
        }
    }


}